<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width">
	<title>玩转css阴影技巧和细节</title>
	<style type="text/css">
		.red{color:#ef3212;padding-left:2rem;margin-top:20px;}
		ul,li{list-style: none;}
		ul>li{margin-top:10px;}
		pre{font-size: 14px;line-height: 20px;}
		.disFlex{display: flex;}
		.flex{flex: 1}
		.ac{text-align: center;}
		.pl2{padding-left: 2rem}
		.box{width:150px;height:150px;border:1px solid #aaa;}
		.middle{margin-right:auto;margin-left: auto;}
		.inline{display: inline-block;}
		.shadow1{box-shadow: 3px 3px 1px 1px #666;}
		.shadow2{box-shadow: 0 0 3px 3px #666;}
		.shadow_left{box-shadow: -7px 0 5px -5px #666; }
		.shadow_right{box-shadow: 7px 0 5px -5px #666; }
		.shadow_top{box-shadow:0 -7px  5px -5px #666;}
		.shadow_bottom{box-shadow:0 7px  5px -5px #666;} 
		.shadow3{width:80px;height:80px;border:1px solid #333;
			box-sizing:border-box;box-shadow:80px 60px 0 0 #000;
		}
		.h160{height: 160px;}
		.shadow4{position: relative;width:250px;height:150px;}
		.shadow4::before{content:"";position: absolute;width:50px;height: 50px;top:-50px;left:-50px;
		box-shadow: 50px 50px #000,150px 50px #000,250px 50px #000,
					50px 100px #666,150px 100px #666,250px 100px #666,
					50px 150px #aaa,150px 150px #aaa,250px 150px #aaa}
		.rang{width:250px;height:40px;}	
		.orange{background: hsl(48,100%,50%);}		
		.o_shadow{box-shadow: 5px 5px 5px hsl(48,100%,20%);}
		.mt10{margin-top: 10px;}
		.mt5{margin-top:5px;}
		.bd5{border-radius: 5px;}
		.pos{position: relative;}
		.bold{font-weight: bold;}
		.trans_border::before{content:"";position: absolute;width:230px;height: 30px;z-index: -1;background: #926212;border-radius: 5px;transform: rotate(-4deg);top:10px;left:5px;}
		.trans_border.filter::before{
			box-shadow:5px 5px 5px hsl(48,100%,20%);
		}
		.text{font-size: 24px;padding-left: 3rem;color:orange;}
		.text_shadow1{text-shadow: 6px 6px 3px hsla(14,100%,30%,1);font-size:24px;color:orange;}
		.text_shadow2{
  text-shadow: 0px 0px #992400,1px 1px #992400,2px 2px #992400,3px 3px #992400,4px 4px #992400,5px 5px #992400,6px 6px #992400,7px 7px #992400,8px 8px #992400,9px 9px #992400,10px 10px #992400,11px 11px #992400,12px 12px #992400,13px 13px #992400,14px 14px #992400,15px 15px #992400,16px 16px #992400,17px 17px #992400,18px 18px #992400,19px 19px #992400,20px 20px #992400; 

}
		.text_shadow3 {text-shadow: 0px 0px #992400,1px 1px rgba(152, 36, 1, 0.98),2px 2px rgba(151, 37, 2, 0.96),3px 3px rgba(151, 37, 2, 0.94),4px 4px rgba(150, 37, 3, 0.92),5px 5px rgba(149, 38, 4, 0.9),6px 6px rgba(148, 38, 5, 0.88),7px 7px rgba(148, 39, 5, 0.86),8px 8px rgba(147, 39, 6, 0.84),9px 9px rgba(146, 39, 7, 0.82),10px 10px rgba(145, 40, 8, 0.8),11px 11px rgba(145, 40, 8, 0.78),12px 12px rgba(144, 41, 9, 0.76),13px 13px rgba(143, 41, 10, 0.74),14px 14px rgba(142, 41, 11, 0.72),15px 15px rgba(142, 42, 11, 0.7),16px 16px rgba(141, 42, 12, 0.68),17px 17px rgba(140, 43, 13, 0.66),18px 18px rgba(139, 43, 14, 0.64),19px 19px rgba(138, 43, 15, 0.62),20px 20px rgba(138, 44, 15, 0.6); }
		.avator{
			position: relative;background: url(add_item.png) no-repeat center center;background-size: 100% 100%;width:120px;height:120px;
		}
		.avator::after{
			content: "";position: absolute;top:10%;width: 100%;height: 100%;background:inherit;background-size: 100%  100%;
			filter:blur(10px) brightness(80%) opacity(.8); z-index:-1;
		}
		.black_box{
			background: #000;
			width:400px;
			height:360px;
		}
		.douyin1{
			position: relative;left:200px;top:30px;width: 37px;height: 218px;background-color: #fff;
		}
		.douyin1:before{
			content:"";position: absolute;width: 100px;height: 100px;border:37px solid #fff; border-top:37px solid transparent;border-radius:50%;top:123px;left:-137px;transform: rotate(45deg);
		}
		.douyin1:after{
			content: "";position: absolute;width: 140px;height: 140px;border:30px solid transparent;border-bottom: 30px solid #fff;top:-100px; right:-172px;border-radius: 100%;transform: rotate(45deg);
		}
		.dy_fliter{
			filter: drop-shadow(-10px -10px 0 #24f6f0);
		}
		.douyin1.green_filter{
			filter:drop-shadow(-10px -10px 0 #24f6f0) contrast(150%) brightness(110%);box-shadow:11.6px 10px 0 0 #fe2d52;
		}

		.douyin1.green_filter:before{
		    filter:drop-shadow(16px 0px 0 #fe2d52);
		}
		.douyin1.green_filter:after{
		    filter:drop-shadow(16px 0px 0 #fe2d52);
		}
	</style>
</head>
<body>
<pre>
	CSS中可以实现阴影效果的属性是box-shadow 和 fitler:drop-shadow，
	但是css阴影效果不一定是box-shadow 和filter:drop-shaow，其他属性也可以实现
</pre>
<div class="red">单侧投影</div>
	先看一下两侧的投影和四侧的投影
	<div class="disFlex">
		<div class="flex">
			<div class="box shadow1 middle"></div>
			box-shadow: 3px 3px 1px 1px #666;
		</div>
		<div class="flex">
			<div class="box shadow2 middle"></div>
			box-shadow: 0 0 3px 3px #666;
		</div>
	</div>
<pre>
	OK，那如果生成单侧的阴影呢？
	我们先来看box-shadow的定义；
	box-shadow: 3px 3px 1px 1px #666;
	4个数值依次表示：
	x方向偏移值，Y反方向偏移值，
	模糊半径，扩张半径

	技巧： 扩张半径可以为负值
	那么如果我们将阴影的模糊半径和负的扩张半径一致，
	我们将看不到任何阴影，这样就可以实现单侧阴影
</pre>
<div class="pl2">
	<ul>
		<li>
			<div class="box shadow_left inline"></div> box-shadow: -7px 0 5px -5px #666; 
		</li>
		<li>
			<div class="box shadow_right inline"></div> box-shadow: 7px 0 5px -5px #666; 
		</li>
		<li>
			<div class="box shadow_top inline"></div> box-shadow:0 -7px  5px -5px #666; 
		</li>
		<li>
			<div class="box shadow_bottom inline"></div> box-shadow:0 -7px  -5px -5px #666; 
		</li>
	</ul>
</div>
<div class="red">投影背景/背景动画</div>
<pre>
	很显然，0=-0，所以当box-shadow的模糊半径和扩张半径都为0的时候，
	可以得到和元素大小一样的阴影，只不过被元素本身遮挡住了，尝试将它
	偏移出来。
	css代码如下
	div{
		width:80px;
		height:80px;
		border:1px solid #333;
		box-sizing:border-box;
		box-shadow:80px 60px 0 0 #000;
	}
	得到如下结果：
</pre>
<div class="pl2 h160">
	<div class="shadow3"></div>
</div>
<div class="pl2">需要注意box-shadow可以设置多个值，比如下行代码：</div>
<pre>
	.shadow{
		position: relative;
		width:250px;
		height:150px;
	}
	.shadow::before{
		content:"";
		position: absolute;
		width:50px;
		height: 50px;
		top:-50px;
		left:-50px;
		box-shadow: 50px 50px #000,150px 50px #000,250px 50px #000,
			50px 100px #666,150px 100px #666,250px 50px #666,
			50px 150px #aaa,150px 150px #aaa,250px 150px #aaa
	}
</pre>
<div class="pl2">
	<div class="shadow4"></div>
</div>
<div class="red">立体投影</div>
<pre>
	这里说的立体投影，并不一定是使用了box-shadow、text-shaodw
	或者drop-shadow，而是我们使用了其他元素或者属性模拟元素的
	阴影，这样能突破box-shadow这类元素的一些定位局限，让阴影的
	位置/大小/元素/模糊度可以更加灵活。
	ok,先看一个demo,通过自定义阴影的位置，让它更加立体。
</pre>
<div class="pl2">
	<div class="rang orange o_shadow"></div>
</div>
<pre>
	上图div只是带了一个非常浅的box-shadow,看上去和立体没有什么
	关系，那么我们通过div的伪元素给它一个和原图边角形状类似的图形，
	再通过transform位移一下，可能是这样的：
</pre>
<div class="pl2">
	<div class="rang orange bd5 pos trans_border"></div>
</div>
<div class="pl2">
	最后再对这个元素做一些虚化处理，就可以实现一个边角看起来被撕开的立体效果了。
	<div class="rang orange bd5 pos trans_border filter"></div>
</div>
<pre>
	总结一下：
	立体投影的关键点在于利用伪元素生成一个和父元素
	相近的元素，然后对其进行rotate以及定位到合适的
	位置，再赋予阴影操作。
	颜色的运用也很重要，阴影的颜色通常比本身颜色要更
	深，这里使用HSL表示颜色更容易操作，l控制颜色的明暗度。
</pre>
<div class="red">文字立体投影/文字长阴影</div>
<div class="mt10">正常而言，我们使用text-shadow来生成文字阴影，像这样：</div>
<pre>
	< div >Txt Shadow< /div >
	div{text-shadow:6px 6px 3px hsla(14,100%,30%,1);}
</pre>
<div class="mt10 text_shadow1 pl2">Txt shadow</div>
<div class="pl2">这样还是可以，就是不够立体。要做到立体文字阴影，最常见的方法就是使用多层文字阴影叠加。</div>
<div class="mt10 pl2">
	注意：text-shadow和box-shadow一样，也是可以叠加多层的，
	但是对于单个元素而言，drop-shadow的话就只能是一层。
</div>
<div class="pl2">那我们试着叠加50层文字阴影，看一下效果。不过不要手写，用SASS/LESS帮忙写一个50层阴影的function就好，
我们每向右和向下偏移1px，生成一层text-shadow:</div>
<pre>
	@function makeLongShadow($color){
	  $val:0px 0px $color;

	  @for $i from  1 through 20{
	    $val:#{$val},#{$i}px #{$i}px #{$color},
	  }
	  @return $val;
	}
	div{
	  text-shadow:makeLongShadow(hsl(14,100%,30%))
	}
</pre>
<div>
	编译后的css代码以及效果
</div>
<div>
	css code <br>
	div {
  text-shadow: 0px 0px #992400,1px 1px #992400,2px 2px #992400,3px 3px #992400,4px 4px #992400,5px 5px #992400,6px 6px #992400,7px 7px #992400,8px 8px #992400,9px 9px #992400,10px 10px #992400,11px 11px #992400,12px 12px #992400,13px 13px #992400,14px 14px #992400,15px 15px #992400,16px 16px #992400,17px 17px #992400,18px 18px #992400,19px 19px #992400,20px 20px #992400; }
</div>
<div class="text text_shadow2">txt shadow</div>
<div class="pl2 mt10">恩，不错，很立体，但是就是丑，问题出在，阴影其实是存在明暗度和透明度都是渐变的，所以对于渐进的每一层文字阴影/明暗度/透明度应该都是不断变化的。这个需求，同样也依靠scss去实现</div>
<div class="mt10 pl2">
	scss有两个颜色函数：fade-out和desaturate： <br>
	fade-out改变颜色的透明度，让颜色更加透明 <br>
	desaturate改变颜色的饱和度值，让颜色更少的饱和。
</div>
<div class="pl2">
	还是将上面的makeLongShadow函数进行修改一下：
</div>
<pre>
	@function makeLongShadow($color){
	  $val:0px 0px $color;

	  @for $i from 1 through 20{
	  	$color:fade-out(desaturate($color,1%),.02);
	    $val:#{$val},#{$i}px #{$i}px #{$color};
	  }
	  @return $val;
	}
	div{
	  text-shadow:makeLongShadow(hsl(14,100%,30%))
	}
</pre>
<div class="mt10 pl2">
	得到编译后的css code和相应的效果 <br>
	css code <br>
	div {
  text-shadow: 0px 0px #992400,1px 1px rgba(152, 36, 1, 0.98),2px 2px rgba(151, 37, 2, 0.96),3px 3px rgba(151, 37, 2, 0.94),4px 4px rgba(150, 37, 3, 0.92),5px 5px rgba(149, 38, 4, 0.9),6px 6px rgba(148, 38, 5, 0.88),7px 7px rgba(148, 39, 5, 0.86),8px 8px rgba(147, 39, 6, 0.84),9px 9px rgba(146, 39, 7, 0.82),10px 10px rgba(145, 40, 8, 0.8),11px 11px rgba(145, 40, 8, 0.78),12px 12px rgba(144, 41, 9, 0.76),13px 13px rgba(143, 41, 10, 0.74),14px 14px rgba(142, 41, 11, 0.72),15px 15px rgba(142, 42, 11, 0.7),16px 16px rgba(141, 42, 12, 0.68),17px 17px rgba(140, 43, 13, 0.66),18px 18px rgba(139, 43, 14, 0.64),19px 19px rgba(138, 43, 15, 0.62),20px 20px rgba(138, 44, 15, 0.6); }
</div>
<div class="text text_shadow3">Txt Shadow</div>
<div class="mt10">附赠一个使用了透明色叠加底色的多重线性渐变实现文字立体阴影的效果：https://codepen.io/Chokcoco/pen/XxQJEB?editor=1100</div>
<div class="red">长投影</div>
<div class="pl2">上面提到了通过多层阴影叠加实现文字的立体阴影，运用在div这些容器也是可以的。不过还有一种有意思的方法，假设我们有一个矩形元素，希望给他添加一个长阴影，可以参考下面这个链接线性渐变模拟长阴影(https://codepen.io/Chokcoco/pen/qjvVGy)</div>
<div class="red">彩色投影</div>
<div class="pl2">
	通常而言：我们生成阴影的方式大多数是box-shadow, filter, drop-shadow(), text-shadow。但是使用它们生成的阴影只能是单色或者是同色系。想要生成渐变色的阴影，当然是不可以的！ <br>
	但是可以通过巧妙地利用fiter:blur模糊滤镜，我们可以假装生成渐变色或者说是颜色丰富的阴影效果。
</div>
<div class="pl2">
	我们有以下面这张图为例 <br>
	<img src="add_item.png"> <br>
	下面利用滤镜，给他添加一层和原颜色相仿的阴影效果，核心css代码如下：
	<pre>
	.avator{
		position: relative;
		background: url(add_item.png) no-repeat center center;
		background-size: 100% 100%;
	}
	.avator::after{
		content: "";
		position: absolute;
		top:10%;
		width: 100%;
		height: 100%;
		background:inherit;
		background-size: 100%  100%;
		filter:blur(10px) brightness(80%) opacity(.8);
		z-index:-1;
	}
	</pre>
	<div class="mt10">看看效果</div>
	<div class="avator mt5"></div>
</div>
<div class="mt5 pl2">
	简单来说，就是利用伪元素生成一个与原图一样大小的新图叠加在原图之下，然后利用滤镜模糊 filter:blur()配合其他的亮度/对比度透明度等滤镜，制作出一个虚幻的影子，伪装成原图的阴影效果。 <br>
	核心 code: filter:blur(10px) brightness(80%) opacity(.8);
</div>
<div class="red">使用box-shadow实现的灯光效果</div>
<div class="pl2">上面主要是一些实现各种阴影的方法，接下来是效果篇。先来看看使用box-shaodw实现的一些灯光效果</div>
<div class="bold"> box-shadow实现霓虹氖灯文字效果</div>
<div class="pl2">
	这个效果也叫Neon,Codepen山脉有很多类似的效果，本质上都是大范围的box-shaodw过渡效果和白色文字的叠加：	<br>
	<img src="640.gif"> <br>
	可以参考这个链接：Codepen Demo - box-shadow实现霓虹氖灯文字效果：https://codepen.io/Chokcoco/pen/WaLDwX
</div>
<div class="bold">使用box-shadow实现阴影灯光show</div>
<div class="pl2">
	和上面的效果类似，本质上都是多层阴影的过渡 <br>
	<img src="6401.gif"> <br>
	效果链接：CodePen Demo - 使用box-shadow实现阴影灯光show：https://codepen.io/Chockcoco/pen/ReOgvq
</div>
<div class="bold">使用drop-shadow|box-shaadow实现单标签抖音LOGO</div>
<div class="pl2">
	既然是标题是“你不知道的CSS阴影技巧和细节”，那肯定要有一些奇技淫巧。 <br>
	先来看一下，单个标签实现仿抖音LOGO，当然由于限定在一个元素，所以细节方面还是有很多瑕疵。 <br>
	先来看看抖音的LOGO， <br>
	分析一下可以得到其实LOGO由三个类似J的形状组成，而单独拎出一个，又可以把它拆分成四分之一圆、|以及\组成 。正好一个元素加上它的两个伪元素，刚好可以凑成这三个形状，就开始实现以下吧。 <br>
	<pre>
	< div >< /div >
	.douyin1{
		position: relative;
		width: 37px;
		height: 218px;
		background-color: #fff;
	}
	.douyin1:before{
		content:"";
		position: absolute;
		width: 100px;
		height: 100px;
		top:123px;
		left:-137px;
		border:37px solid #fff; 
		border-top:37px solid transparent;
		border-radius:50%;
		transform: rotate(45deg);
	}
	.douyin1:after{
		content: "";
		position: absolute;
		width: 140px;
		height: 140px;
		border:30px solid transparent;
		border-bottom: 30px solid #fff;
		top:-100px; 
		right:-172px;
		border-radius: 100%;
		transform: rotate(45deg);
	}
	</pre>
	<div class="black_box">
		<div class="douyin1"></div>
	</div>
	接下来就是轮到filter:drop-shadow()登场，它可以在元素呈现之前，为元素的渲染提供一些效果。最常见的也就是用它渲染整体阴影。 <br>
	我们通常会用它来实现对话框的小三角与整体对话框的阴影效果。像下面这样：左边使用drop-shadow的效果，右边是使用普通的box-shaodw的效果。 <br>
	如果对drop-shadow的基本用法不了解，可以参看这个链接：CodePen Dome - Drop-shadow vs Box-shadow (2) By Kseso(https://codepen.io/Kseso/pen/Ajamv) <br>
	OK，回到之前说的，我们使用filter:drop-shadow()生成它的第一层左边的蓝色阴影，添加在主体div:
<pre>
	< div >< /div >
	.douyin1{
		position: relative;
		width: 37px;
		height: 218px;
		background-color: #fff;
		filter:drop-shadow(-10px -10px 0 #24f6f0);
		&:before,
		&after{
		    ....
		}
	}	
</pre>
	<div class="black_box">
		<div class="douyin1 dy_fliter"></div>
	</div>
	<div>
		好然后我们只需要再添加一层红色filter:drop-shadow()在右侧就大功搞成了？ <br>
		敲黑板！上面提到过，和box-shadow和text-shadow一样是可以叠加多层的，但是对于单个元素而言，drop-shadow的话只能是一层。 <br>
		也就是说，无法在div上再使用filter:drop-shadow生成另一侧的阴影，不过还好，可以在两个伪元素的filter:drop-shadow上面去尝试： <br>
		<pre>
	< div >< /div >
	.douyin1{
		position: relative;
		width: 37px;
		height: 218px;
		background-color: #fff;

		filter:drop-shadow(-10px -10px 0 #24f6f0) contrast(150%) brightness(110%);
		box-shadow:11.6px 10px 0 0 #fe2d52;

		&:before{
		    ....
		    filter:drop-shadow(16px 0px 0 #fe2d52);
		}
		&:after{
			....
		    filter:drop-shadow(16px 0px 0 #fe2d52);
		}
	}	
		</pre>
		<div class="black_box">
			<div class="douyin1 dy_fliter green_filter"></div>
		</div>
		<div>Code Dome - 单标签实现抖音LOGO(https://codepen.io/Chokcoco/pen/qJQmyY)</div>
	</div>
</div>
<div class="pl2">
	<div class="bold">总结一下</div>
	主要借助了两个伪元素实现了整体结构，借助了drop-shadow生成一层整体阴影。 <br>
	drop-shadow只能实现单层阴影，所以另一层阴影需要多尝试。 <br>
	contrast(150%) brightness(110%)可以增强图像的对比度和亮度，更贴近抖音LOGO的效果。
</div>
<div class="pl2">
	实际上抖音的LOGO应该是两个类似J形的形状重叠在一起，重叠的部分为白色，非重叠的部分分为各自原色。 <br>
	这个效果可以利用css的混合模式mix-blend-mode也是可以是实现的，可以参考这个链接： <br>
	CodePen Dome - 使用mix-blend-mode实现抖音 (https://codepen.io/Chokcoco/pen/oQxQyw)
 </div>


</body>
</html>